﻿Imports System
Imports System.CodeDom
Imports System.Collections
Imports System.Diagnostics.CodeAnalysis
Imports System.Globalization
Imports System.IO
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler
Imports System.Workflow.ComponentModel.Design
Imports System.Workflow.ComponentModel.Serialization
Imports System.Xml

Namespace System.Workflow.Activities.Rules
    Friend Class ConditionHelper
        ' Methods
        Friend Shared Function CloneObject(ByVal original As Object) As Object
            If (original Is Nothing) Then
                Return Nothing
            End If
            If original.GetType.IsValueType Then
                Return original
            End If
            Dim cloneable As ICloneable = [TryCast](original,ICloneable)
            If (cloneable Is Nothing) Then
                Throw New NotSupportedException(String.Format(CultureInfo.CurrentCulture, Messages.NotCloneable, New Object() { original.GetType.FullName }))
            End If
            Return cloneable.Clone
        End Function

        Friend Shared Sub CloneUserData(ByVal original As CodeObject, ByVal result As CodeObject)
            Dim obj2 As Object
            For Each obj2 In original.UserData.Keys
                Dim key As Object = ConditionHelper.CloneObject(obj2)
                Dim obj4 As Object = ConditionHelper.CloneObject(original.UserData.Item(obj2))
                result.UserData.Add(key, obj4)
            Next
        End Sub

        Friend Shared Sub Flush_Rules_DT(ByVal serviceProvider As IServiceProvider, ByVal activity As Activity)
            Dim definitions As RuleDefinitions = DirectCast(activity.GetValue(RuleDefinitions.RuleDefinitionsProperty), RuleDefinitions)
            If (Not definitions Is Nothing) Then
                Dim service As WorkflowDesignerLoader = DirectCast(serviceProvider.GetService(GetType(WorkflowDesignerLoader)), WorkflowDesignerLoader)
                If (Not service Is Nothing) Then
                    Dim filePath As String = String.Empty
                    If Not String.IsNullOrEmpty(service.FileName) Then
                        filePath = Path.Combine(Path.GetDirectoryName(service.FileName), Path.GetFileNameWithoutExtension(service.FileName))
                    End If
                    filePath = (filePath & ".rules")
                    [Using] writer As TextWriter = service.GetFileWriter(filePath)
                        If (Not writer Is Nothing) Then
                            [Using] writer2 As XmlWriter = Helpers.CreateXmlWriter(writer)
                                New WorkflowMarkupSerializer().Serialize(writer2, definitions)
                            End [Using]
                        End If
                    End [Using]
                End If
            End If
        End Sub

        Friend Shared Function GetContextType(ByVal typeProvider As ITypeProvider, ByVal currentActivity As Activity) As Type
            Dim type As Type = Nothing
            Dim str As String = String.Empty
            Dim declaringActivity As Activity = Nothing
            If Helpers.IsActivityLocked(currentActivity) Then
                declaringActivity = Helpers.GetDeclaringActivity(currentActivity)
            Else
                declaringActivity = Helpers.GetRootActivity(currentActivity)
            End If
            If (Not declaringActivity Is Nothing) Then
                str = [TryCast](declaringActivity.GetValue(WorkflowMarkupSerializer.XClassProperty),String)
                If Not String.IsNullOrEmpty(str) Then
                    type = typeProvider.GetType(str, False)
                End If
                If (type Is Nothing) Then
                    type = typeProvider.GetType(declaringActivity.GetType.FullName)
                End If
                If (type Is Nothing) Then
                    type = declaringActivity.GetType
                End If
            End If
            Return type
        End Function

        Friend Shared Function GetRuleDefinitionsFromManifest(ByVal workflowType As Type) As RuleDefinitions
            If (workflowType Is Nothing) Then
                Throw New ArgumentNullException("workflowType")
            End If
            Dim definitions As RuleDefinitions = Nothing
            If ConditionHelper.rulesResources.ContainsKey(workflowType) Then
                definitions = DirectCast(ConditionHelper.rulesResources.Item(workflowType), RuleDefinitions)
            Else
                Dim name As String = (workflowType.Name & ".rules")
                Dim manifestResourceStream As Stream = workflowType.Module.Assembly.GetManifestResourceStream(workflowType, name)
                If (manifestResourceStream Is Nothing) Then
                    manifestResourceStream = workflowType.Module.Assembly.GetManifestResourceStream(name)
                End If
                If (Not manifestResourceStream Is Nothing) Then
                    [Using] reader As StreamReader = New StreamReader(manifestResourceStream)
                        [Using] reader2 As XmlReader = XmlReader.Create(reader)
                            definitions = [TryCast](New WorkflowMarkupSerializer().Deserialize(reader2),RuleDefinitions)
                        End [Using]
                    End [Using]
                End If
                SyncLock ConditionHelper.rulesResources
                    ConditionHelper.rulesResources.Item(workflowType) = definitions
                End SyncLock
            End If
            If (Not definitions Is Nothing) Then
                definitions = definitions.Clone
            End If
            Return definitions
        End Function

        Friend Shared Function IsNonNullableValueType(ByVal type As Type) As Boolean
            Return ((type.IsValueType AndAlso Not type.IsGenericType) AndAlso (Not type Is GetType(String)))
        End Function

        Friend Shared Function IsNullableValueType(ByVal type As Type) As Boolean
            Return ((type.IsValueType AndAlso type.IsGenericType) AndAlso type.GetGenericTypeDefinition.Equals(GetType(Nullable([Of] ))))
        End Function

        <SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")> _
        Friend Shared Function Load_Rules_DT(ByVal serviceProvider As IServiceProvider, ByVal activity As DependencyObject) As RuleDefinitions
            Dim definitions As RuleDefinitions = DirectCast(activity.GetValue(RuleDefinitions.RuleDefinitionsProperty), RuleDefinitions)
            If (definitions Is Nothing) Then
                Dim service As WorkflowDesignerLoader = DirectCast(serviceProvider.GetService(GetType(WorkflowDesignerLoader)), WorkflowDesignerLoader)
                If (Not service Is Nothing) Then
                    Dim filePath As String = String.Empty
                    If Not String.IsNullOrEmpty(service.FileName) Then
                        filePath = Path.Combine(Path.GetDirectoryName(service.FileName), Path.GetFileNameWithoutExtension(service.FileName))
                    End If
                    filePath = (filePath & ".rules")
                    Try 
                        [Using] reader As TextReader = service.GetFileReader(filePath)
                            If (reader Is Nothing) Then
                                definitions = New RuleDefinitions
                            Else
                                [Using] reader2 As XmlReader = XmlReader.Create(reader)
                                    definitions = [TryCast](New WorkflowMarkupSerializer().Deserialize(reader2),RuleDefinitions)
                                End [Using]
                            End If
                        End [Using]
                    Catch exception1 As Exception
                        definitions = New RuleDefinitions
                    End Try
                End If
                activity.SetValue(RuleDefinitions.RuleDefinitionsProperty, definitions)
            End If
            Return definitions
        End Function

        Friend Shared Function Load_Rules_RT(ByVal declaringActivity As Activity) As RuleDefinitions
            Dim ruleDefinitionsFromManifest As RuleDefinitions = [TryCast](declaringActivity.GetValue(RuleDefinitions.RuleDefinitionsProperty),RuleDefinitions)
            If (ruleDefinitionsFromManifest Is Nothing) Then
                ruleDefinitionsFromManifest = ConditionHelper.GetRuleDefinitionsFromManifest(declaringActivity.GetType)
                If (Not ruleDefinitionsFromManifest Is Nothing) Then
                    declaringActivity.SetValue(RuleDefinitions.RuleDefinitionsProperty, ruleDefinitionsFromManifest)
                End If
            End If
            Return ruleDefinitionsFromManifest
        End Function


        ' Fields
        Private Shared rulesResources As Hashtable = New Hashtable
    End Class
End Namespace

